/*
 * This class is the service window of the bank. It carries the main business logics.
 * 
 * In this class, The VIP and express service window will serve VIP and express customers first. If there are no VIP and express customers,
 * they will serve common customers.
 * 
 * Copy right with charles. You are free to use and modify the code. Please contact author - charles@webcheng.net for commercial use.
 * */

package net.webcheng;

import java.util.Random;

public class ServiceWindow implements Runnable{
	//Service Window type is the same as ticket type. Use ticket type as service window type.
	private TicketType wType;
	//Ticket Machine is used to get the first customer waiting in the queue.
	private TicketMachine tm = TicketMachine.getInstance();
	
	//Process customer who is in the queue.
	public void processCustomer(Ticket t){
		System.out.println(Thread.currentThread().getName()+"start to process ticket:"+t.getSequenceNo()+". Ticket type:"+t.getTicketType());
		if(t.getTicketType()!=null){//customer must have a ticket with ticket type.
			//Process common customers
			if(t.getTicketType().equals(TicketType.COMMON)){
				try {
					//It will take a random time between 1 second to 5 seconds to process normal customer.
					Random r = new Random();
					int random = r.nextInt(CONSTANTS.MAX_PROCESSTIME-CONSTANTS.MIN_PROCESSTIME);
					System.out.println(Thread.currentThread().getName()+" process "+t.getSequenceNo()+" for "+random+" milliseconds.");
					Thread.sleep(random);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
			//process express customers
			if(t.getTicketType().equals(TicketType.EXPRESS)){
				try {
					//It will take 1 second to process express customer.
					Thread.sleep(CONSTANTS.MIN_PROCESSTIME);
					System.out.println(Thread.currentThread().getName()+" process "+t.getSequenceNo()+" for "+CONSTANTS.MIN_PROCESSTIME+" milliseconds.");
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
			//process VIP customers
			if(t.getTicketType().equals(TicketType.VIP)){
				try {
					//It will take 5 seconds to process VIP customer.
					Thread.sleep(CONSTANTS.MAX_PROCESSTIME);
					System.out.println(Thread.currentThread().getName()+ " process "+t.getSequenceNo()+" for "+CONSTANTS.MAX_PROCESSTIME+" milliseconds.");
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			System.out.println(Thread.currentThread().getName()+" finish processing ticket:"+t.getSequenceNo()+". Ticket type:"+t.getTicketType());
		}
	}

	public void setwType(TicketType wType) {
		this.wType = wType;
	}

	public TicketType getwType() {
		return wType;
	}

	@Override
	public void run() {
		while(true){
			Ticket t = null;
			switch(wType){
				case COMMON:
					t = tm.fetchTicketWithType(TicketType.COMMON);//Serve a normal customer
					break;
				case EXPRESS:
					t = tm.fetchTicketWithType(TicketType.EXPRESS);//Serve an express customer
					if(null==t)//if there is no express customer, serve a normal customer
						t = tm.fetchTicketWithType(TicketType.COMMON);
					break;
				case VIP:
					t = tm.fetchTicketWithType(TicketType.VIP);//Serve a VIP customer
					if(null==t)//if there is no VIP customer, serve a normal customer
						t = tm.fetchTicketWithType(TicketType.COMMON);
					break;
			}
			if(null==t){//If there is no customer waiting at all, wait a second and check again after waiting.
				System.out.println(Thread.currentThread().getName()+": no customers waiting now. Wait another second.");
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			else
				processCustomer(t);
	
		}
	}
}